package com.zkh.myutils.system;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import com.zkh.myutils.io.IOUtils;
import com.zkh.myutils.json.JSONObject;
import com.zkh.myutils.utils.Assert;
import com.zkh.myutils.utils.ConfigureUtils;
import com.zkh.myutils.utils.StringUtils;
import com.zkh.myutils.utils.Utils;

/**
 * 配置加载器
 * @author zkh
 */
public class ConfigLoader {
	
	//全局配置
	private static Map<String, Object> configMap;
	
	/**
	 * 加载配置（该方法只会加载一次）
	 */
	public static Map<String, Object> initialize() {
		return initialize(null);
	}
	
	/**
	 * 加载配置（该方法只会加载一次）
	 * @param profile 指定模块，该参数不为空时，将覆盖application.my文件中的profile配置项
	 */
	public static Map<String, Object> initialize(String profile) {
		//未加载，则先加载
		if(configMap==null) {
			//加载配置
			synchronized (ConfigLoader.class) {
				//初始化容器
				configMap = new TreeMap<>();
				//加载配置
				InputStream inputStream = ConfigLoader.class.getClassLoader().getResourceAsStream("application.my");
				//为空
				if(inputStream==null) {
					//抛出异常
					System.out.println("未找到配置文件：application.my");
				}else {
					//加载文件模块
					String prof = null;
					try {
						//配置整合（自动关闭流）
						configMap.putAll(ConfigureUtils.loadMy(inputStream));
						//获取加载文件
						prof = (String) configMap.get("profile");
						//模块已赋值
						if(StringUtils.isNotEmpty(profile)){
							prof = profile;
						}
					} finally {
						IOUtils.closeQuietly(inputStream);
					}
					//存在
					if(StringUtils.isNotEmpty(prof)) {
						//加载配置文件
						inputStream = ConfigLoader.class.getClassLoader().getResourceAsStream("application_" + prof + ".my");
						//存在，则加载
						if(inputStream!=null) {
							try {
								//解析配置文件
								Map<String, Object> nextMap = ConfigureUtils.loadMy(inputStream);
								//合并
								mergerMap(configMap, nextMap);
							}finally {
								IOUtils.closeQuietly(inputStream);
							}
						}
					}
				}
			}
		}
		//返回容器
		return configMap;
	}
	
	/**
	 * 将nextMap参数值合并到lastMap参数
	 */
	@SuppressWarnings({ "unchecked" })
	private static void mergerMap(Map<String, Object> lastMap, Map<String, Object> nextMap) {
		//遍历合并配置
		for(Entry<String, Object> kv: nextMap.entrySet()) {
			//key
			String key = kv.getKey();
			//获取值
			Object lastValue = lastMap.get(key), value = kv.getValue();
			//值均为Map，需要进行合并
			if(lastValue instanceof Map && value instanceof Map) {
				//合并
				mergerMap((Map<String, Object>) lastValue, (Map<String, Object>) value);
			}else {
				lastMap.put(key, value);
			}
		}
	}
	
	/**
	 * 获取全部配置
	 */
	public static Map<String, Object> getAll(){
		//初始化并获取配置
		return initialize();
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 */
	public static String getString(String key) {
		return getString(key, false);
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 * @param defaultValue 默认值
	 * @return
	 */
	public static String getString(String key, String defaultValue) {
		return getString(key, defaultValue, false);
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 * @param ignoreException 是否忽略异常，为true时，如果发生异常，返回null。（如果没有配置可能抛出异常）
	 * @return
	 */
	public static String getString(String key, boolean ignoreException) {
		return getString(key, null, ignoreException);
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 * @param defaultValue 默认值
	 * @param ignoreException 是否忽略配置不存在的异常，为true时，忽略并返回默认值。（如果没有配置可能会抛出异常）
	 * @return
	 */
	public static String getString(String key, String defaultValue, boolean ignoreException) {
		try {
			return Assert.getOrDefault((String) getValue(key), defaultValue);
		}catch (IllegalArgumentException | NullPointerException e) {
			//忽略异常，直接返回null
			if(ignoreException) {
				return defaultValue;
			}
			//抛出异常
			throw e;
		}
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 * @return
	 */
	public static <T> List<T> getList(String key) {
		return getList(key, false);
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 * @param defaultValue 默认值
	 * @return
	 */
	public static <T> List<T> getList(String key, List<T> defaultValue) {
		return getList(key, defaultValue, false);
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 * @param ignoreException 是否忽略配置不存在的异常，为true时，忽略并返回默认值。（如果没有配置可能会抛出异常）
	 * @return
	 */
	public static <T> List<T> getList(String key, boolean ignoreException) {
		return getList(key, null, ignoreException);
	}
	
	/**
	 * 获取指定配置
	 * @param key 键
	 * @param defaultValue 默认值
	 * @param ignoreException 是否忽略配置不存在的异常，为true时，忽略并返回默认值。（如果没有配置可能会抛出异常）
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> getList(String key, List<T> defaultValue, boolean ignoreException) {
		try {
			return Assert.getOrDefault((List<T>) getValue(key), defaultValue);
		}catch(IllegalArgumentException | NullPointerException e) {
			//忽略异常
			if(ignoreException) {
				return defaultValue;
			}
			//抛出异常
			throw e;
		}
	}
	
	/**
	 * 获取指定配置
	 * @param key 配置属性
	 * @param clazz 要转换的实体
	 */
	public static <T> T getEntity(String key, Class<T> clazz){
		return getEntity(key, clazz, false);
	}
	
	/**
	 * 获取指定配置
	 * @param key 配置属性
	 * @param clazz 要转换的实体
	 * @param ignoreException 是否忽略配置不存在的异常，为true时，忽略并按空配置处理。（如果没有配置可能会抛出异常）
	 */
	public static <T> T getEntity(String key, Class<T> clazz, boolean ignoreException){
		try {
			return new JSONObject(getValue(key)).parseEntity(clazz);
		}catch (IllegalArgumentException | NullPointerException e) {
			//忽略异常
			if(ignoreException) {
				return new JSONObject(null).parseEntity(clazz);
			}
			//抛出异常
			throw e;
		}
	}
	
	/**
	 * 获取指定配置
	 * @param key 配置属性
	 * @return
	 */
	public static <V> Map<String, V> getMap(String key) {
		//初始化并获取配置
		return getMap(key, false);
	}
	
	/**
	 * 获取指定配置
	 * @param key 配置属性
	 * @param defaultValue 默认值
	 * @return
	 */
	public static <V> Map<String, V> getMap(String key, Map<String, V> defaultValue){
		return getMap(key, defaultValue, false);
	}
	
	/**
	 * 获取指定配置
	 * @param key 配置属性
	 * @param ignoreException 是否忽略配置不存在的异常，为true时，忽略并返回空集合。（如果没有配置可能会抛出异常）
	 * @return
	 */
	public static <V> Map<String, V> getMap(String key, boolean ignoreException){
		return getMap(key, null, ignoreException);
	}
	
	/**
	 * 获取指定配置
	 * @param key 配置属性
	 * @param defaultValue 默认值
	 * @param ignoreException 是否忽略配置不存在的异常，为true时，忽略并返回空集合。（如果没有配置可能会抛出异常）
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <V> Map<String, V> getMap(String key, Map<String, V> defaultValue, boolean ignoreException) {
		try {
			//初始化并获取配置
			return Assert.getOrDefault((Map<String, V>) getValue(key), defaultValue);
		}catch(IllegalArgumentException | NullPointerException e) {
			//忽略异常
			if(ignoreException) {
				return new HashMap<>();
			}
			//抛出异常
			throw e;
		}
	}
	
	/**
	 * 获取值
	 * @param key 键
	 * @return
	 */
	private static Object getValue(String key) {
		//获取值
		return Utils.parseValue(key, initialize());
	}
}
